/*
 *  Copyright (C) 2012 Компания ВИТ. web: http://diasled.ru Е-mail:  vit@diasled.ru
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ru.apertum.diasled.model.load;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.LinkedBlockingQueue;
import ru.apertum.diasled.common.Uses;
import ru.apertum.diasled.common.exeptions.QException;
import ru.apertum.diasled.rxtx.PortUtil;

/**
 * В параллельном потоке читаем данные от сканера.
 * @author Evgeniy Egorov, Aperum Projects
 */
public class Generator implements Runnable {

    private final LinkedBlockingQueue<byte[]> queue;
    private final String portName;
    private final int frames;

    public Generator(LinkedBlockingQueue<byte[]> queue, String portName, int frames) {
        this.queue = queue;
        this.portName = portName;
        this.frames = frames;
    }

    @Override
    public void run() {
        final InputStream is = PortUtil.startExam(portName, frames);
        // акпвый байт это какой-т номер, прочитаем его и выкинем, но это признaк того что данные шлются в прогу
        int ate = 0;
        byte[] res = new byte[1];
        boolean flag = false;
        try {
            while (is.available() != 0 || ate < 8) {
                if (is.available() == 0) {
                    ate++;
                    Thread.sleep(125);
                } else {
                    is.read(res);
                    flag = false;
                    break;
                }
            }
        } catch (IOException | InterruptedException ex) {
            flag = true;
        }
        if (flag) {
            queue.offer(ERROR_ARRAY);
            Uses.log.logger.error("Не дождались получения результатов эксперимента из порта " + portName);
            PortUtil.closePortExam();
            return;
        }

        ate = 0;
        try {
            int frameCounter = 0;
            while ((is.available() > 255 || ate < 8) && !Thread.currentThread().isInterrupted()) {
                if (is.available() < 256) {
                    ate++;
                    Thread.sleep(10 + ate * 30);
                } else {
                    ate = 0;
                    final byte[] sb = new byte[256];
                    is.read(sb);
                    queue.offer(sb);
                    frameCounter++;
                }
            }
            if (frameCounter != frames) {
                throw new QException("Количество запрошенных исчитанных фрймов не равно.");
            }
        } catch (IOException | InterruptedException | QException ex) {
            queue.offer(ERROR_ARRAY);
            Uses.log.logger.error("Ошибка при чтении результатов эксперимента из порта " + portName, ex);
            return;
        } finally {
            PortUtil.closePortExam();
        }
        queue.offer(STOP_ARRAY);
        Uses.log.logger.info("Закончилась генерация в БД успешно.");
    }
    final static public byte[] STOP_ARRAY = new byte[333];
    final static public byte[] ERROR_ARRAY = new byte[337];
}
